package cn.bluethink.eguan.core.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import cn.bluethink.eguan.core.entity.EgStaffEntity;
import cn.bluethink.eguan.core.entity.StaffEntity;
import cn.bluethink.eguan.core.mapper.EgStaffMapper;
import cn.bluethink.eguan.filter.NameFilter;
import cn.bluethink.eguan.model.core.EgConfigInfo;
import cn.bluethink.eguan.model.core.EgFaction;
import cn.bluethink.eguan.model.core.EgOType;
import cn.bluethink.eguan.model.core.EgObject;
import cn.bluethink.eguan.model.core.EgPurview;
import cn.bluethink.eguan.model.core.EgRole;
import cn.bluethink.eguan.model.core.EgScope;
import cn.bluethink.eguan.model.core.EgTavern;
import cn.bluethink.eguan.model.core.EgUser;
import cn.bluethink.eguan.result.PageInfo;
import tk.mybatis.mapper.entity.Example;

@Service
public class EgStaffService extends AEgUserPurviewService {

    @Autowired
    private EgConfigInfo configInfo;

    @Autowired
    private EgUserPurviewService userPurviewService;

    @Autowired
    private EgStaffMapper staffMapper;

    public EgStaffService() {
        super();
    }

    @Override
    public Integer posOType() {
        return EgOType.TAVERN;
    }

    @Override
    public EgRole role(EgObject pos, Long uid, EgRole urole) throws Exception {
        // 1、构造查询伙计条件，根据egid和uid查询驿馆伙计
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", pos.getId()).andEqualTo("uid", uid);
        EgStaffEntity staffEntity = staffMapper.selectOneByExample(example);
        // 2、获取当前登录用户的角色和权限
        EgRole role = new EgRole(urole.getRid(), urole.getName(), urole.getPurview());
        // 3、如果为当前驿馆伙计，获取其在staff表中的角色和权限
        if (staffEntity != null) {
            role.or(new EgRole(staffEntity.getRole1(), null, staffEntity.getPurview1()));
        }
        if (pos instanceof EgTavern) {
            EgTavern tavern = (EgTavern) pos;
            // 4、如果当前位置为驿馆并且所属门派不为空，根据用户在当前驿馆中的角色和所属门派中的角色进行计算，获得用户最终的角色和权限
            if (tavern.getFaction() != null && tavern.getFaction().getId() > 0) {
                EgRole frole = userPurviewService.role(tavern.getFaction(), uid, role);
                role = (frole == null ? role : frole);
            }
        }
        // 5、设置用户当前的角色名
        role.setName(configInfo.roleName(role.getRid(), EgScope.TAVERN));
        return role;
    }

    /**
     * 根据条件查询驿馆伙计列表（返回当前伙计所在位置信息）
     * 
     * @param filter
     * @param bLoadRole
     * @return
     * @throws Exception
     */
    public PageInfo<EgUser> query(NameFilter filter, Boolean bLoadRole) throws Exception {
        int pageNum = filter.getPageNum() == null ? 1 : filter.getPageNum();
        int pageSize = filter.getPageSize() == null ? 50 : filter.getPageSize();
        PageHelper.startPage(pageNum, pageSize);
        // 1、根据条件查询实体列表
        Page<StaffEntity> entities = staffMapper.query(filter);
        if (entities != null && entities.size() > 0) {
            // 2、实体转换为模型列表
            List<EgUser> result = entities.stream().map(e -> e.createUser()).collect(Collectors.toList());
            // 3、如果不加载角色信息，直接返回
            if (!bLoadRole)
                return new PageInfo<>(result, entities);
            // 4、设置驿馆伙计当前角色
            result.forEach(r -> {
                String rname = configInfo.roleName(r.getRole().getRid().intValue(), EgScope.TAVERN);
                r.getRole().setName(rname);
            });
            return new PageInfo<>(result, entities);
        }
        return new PageInfo<>(new ArrayList<>());
    }

    /**
     * 批量添加/移除驿馆伙计
     * 
     * @param egid
     * @param uids
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public boolean batchAdd(EgTavern tavern, List<Long> uids) throws Exception {
        Long egid = tavern.getId();
        // 1、构造查询条件，根据当前驿馆Id获取该驿馆中所有伙计列表
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", egid);
        // 2、获取驿馆中伙计列表
        List<EgStaffEntity> entities = staffMapper.selectByExample(example);
        // 3、参数uids赋值给originalList
        List<Long> originalList = new ArrayList<>();
        originalList.addAll(uids);
        // 4、声明新增伙计Id列表和移除伙计Id列表，默认新增伙计列表为uids
        List<Long> insertList = new ArrayList<>();
        List<Long> removeList = new ArrayList<>();
        insertList.addAll(uids);
        // 5、如果驿馆中已有伙计，获取驿馆中伙计列表
        if (entities != null && entities.size() > 0) {
            List<Long> existList = entities.stream().map(e -> e.getUid()).collect(Collectors.toList());
            // 6、去掉已有伙计，获取新增伙计Id列表
            insertList.removeAll(existList);
            // 7、获取移除伙计Id列表
            existList.removeAll(originalList);
            removeList.addAll(existList);
        }

        // 8、获取驿馆掌柜
        EgUser shopkeeper = getShopKeeper(egid);
        // 9、如果新增伙计列表不为空，将其转换为伙计实体并批量添加
        if (insertList != null && insertList.size() > 0) {
            // if(!insertList.contains(shopkeeper.getId()))
            // insertList.add(shopkeeper.getId());
            // 1、根据驿馆Id和用户ID列表 转换成为 驿馆伙计实体对象列表
            List<EgStaffEntity> staffEntities = staffConvert(egid, insertList);
            // 2、批量添加驿馆伙计
            staffMapper.insertStaffs(staffEntities);
        }
        // 10、如果移除伙计列表不为空，批量删除驿馆伙计
        if (removeList != null && removeList.size() > 0) {
            EgFaction faction = tavern.getFaction();
            Integer otid = EgOType.JIANGHU;
            Long fid = 0L;
            // 如果驿馆隶属于门派，将用户位置改成其隶属门派
            if (faction != null && faction.getId() > 0) {
                otid = EgOType.FACTION;
                fid = faction.getId();
            }
            // 如果被移除对象包括掌柜，不删除掌柜对象
            if (removeList.contains(shopkeeper.getId()))
                removeList.remove(shopkeeper.getId());
            // 否则，移除伙计并更新伙计位置
            if (removeList != null && removeList.size() > 0) {
                staffMapper.removeStaffs(egid, removeList);
                staffMapper.updateUsersPos(fid, otid, removeList, egid, EgOType.TAVERN);
            }
        }
        return true;
    }

    /**
     * 移除驿馆伙计
     * 
     * @param egid
     * @param uid
     * @return 返回驿馆Id
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Long remove(Long egid, Long uid) throws Exception {
        EgStaffEntity entity = new EgStaffEntity();
        entity.setEgid(egid);
        entity.setUid(uid);
        int delCount = staffMapper.delete(entity);
        return delCount > 0 ? egid : 0L;
    }

    /**
     * 设置驿馆伙计角色 0.2版本只设置角色（掌柜/伙计），不考虑权限
     * 
     * @param egid
     * @param uid
     * @param bcreate
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgUser setshopkeeper(Long egid, Long uid, boolean bcreate) throws Exception {
        EgRole shopkeeper = configInfo.role(EgRole.SHOPKEEPER).get(EgScope.TAVERN);
        // 1、如果是新增驿馆伙计时赋予该伙计掌柜角色，执行该操作
        if (bcreate) {
            if (updterole(egid, uid, shopkeeper) == 0)
                return null;
            EgUser result = new EgUser(uid, null, null);
            result.setRole(shopkeeper);
            return result;
        }
        // 2、否则，根据egid和uid获取驿馆伙计
        EgStaffEntity entity = detail(egid, uid);
        if (entity == null)
            return null;
        // 3、获取驿馆伙计角色和权限
        EgRole currentUserRole = new EgRole(entity.getRole1(), null, entity.getPurview1());
        // 4、根据当前用户角色和参数role计算得到当前用户最终的角色和权限
        currentUserRole.or(shopkeeper);
        // 5、设置当前用户的角色和权限
        if (updterole(egid, uid, currentUserRole) > 0) {
            EgUser user = entity.createUser();
            user.setRole(currentUserRole);
            return user;
        }
        return null;
    }

    /**
     * 去掉原掌柜在staff表中的角色
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    public boolean removeShopKeeperRole(Long egid) throws Exception {
        EgRole shopkeeper = configInfo.role(EgRole.SHOPKEEPER).get(EgScope.TAVERN);
        EgRole staff = configInfo.role(EgRole.STAFF).get(EgScope.TAVERN);
        // 4、获取当前驿馆中的掌柜
        EgUser oldShopKeeper = getShopKeeper(egid);
        if (oldShopKeeper != null) {
            // 5、获取当前驿馆掌柜的角色和权限
            EgRole oldrole = oldShopKeeper.getRole();
            // 6、去掉原掌柜的掌柜权限
            oldrole.xor(shopkeeper);
            oldrole.or(staff);
            // 7、重新设置原掌柜在staff表中的权限
            if (updterole(egid, oldShopKeeper.getId(), oldrole) == 0)
                return false;
        }
        return true;
    }

    /**
     * 获取驿馆掌柜及其在伙计表中的权限
     * 
     * @param egid
     * @return
     * @throws Exception
     */
    public EgUser getShopKeeper(Long egid) throws Exception {
        EgRole shopkeeper = configInfo.role(EgRole.SHOPKEEPER).get(EgScope.TAVERN);
        EgStaffEntity bossRecord = new EgStaffEntity();
        bossRecord.setEgid(egid);
        bossRecord.setRole1(shopkeeper.getRid());
        EgStaffEntity entity = staffMapper.selectOne(bossRecord);
        if (entity != null) {
            return entity.createUser();
        }
        return null;
    }

    /**
     * 设置驿馆管理权限
     * 
     * @param egid
     * @param uid
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public int setTaverMG(Long egid, Long uid) throws Exception {
        // 1、根据egid和uid获取驿馆伙计
        EgStaffEntity entity = detail(egid, uid);
        if (entity == null)
            return 0;
        // 2、获取驿馆伙计角色和权限，并计算得到当前用户最终的权限
        Integer purview = entity.getPurview1() | EgPurview.TAVERN_MG;
        entity.setPurview1(purview);
        // 4、构造更新条件
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", egid).andEqualTo("uid", uid);
        int result = staffMapper.updateByExampleSelective(entity, example);
        return result;
    }

    /**
     * 根据用户Id获取用户所在驿馆Id列表
     * 
     * @param uid
     * @return
     * @throws Exception
     */
    public List<Long> taverIdsByUser(Long uid) throws Exception {
        EgStaffEntity entity = new EgStaffEntity();
        entity.setUid(uid);
        List<EgStaffEntity> staffs = staffMapper.select(entity);
        if (staffs != null && staffs.size() > 0) {
            List<Long> tids = staffs.stream().map(s -> s.getEgid()).distinct().collect(Collectors.toList());
            return tids;
        }

        return new ArrayList<>();
    }

    /**
     * 根据驿馆Id列表和uid，删除对应驿馆中的伙计
     * 
     * @param egids
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Long removeStaffByEg(List<Long> egids, Long uid) throws Exception {
        Example example = new Example(EgStaffEntity.class);
        example.and().andIn("egid", egids).andEqualTo("uid", uid);
        int delCount = staffMapper.deleteByExample(example);
        return delCount > 0 ? uid : 0L;
    }

    /**
     * 根据驿馆ID列表删除所有的伙计
     * 
     * @param egids
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public Boolean delStaffByEgIds(List<Long> egids) throws Exception {
        Example example = new Example(EgStaffEntity.class);
        // 1、构造删除条件egids和 uid
        example.and().andIn("egid", egids);
        int delCount = staffMapper.deleteByExample(example);
        return delCount > 0 ? true : false;
    }

    /**
     * 判断该用户是否为门派中驿馆的掌柜
     * 
     * @param fid
     *            门派Id
     * @param uid
     *            用户Id
     * @return
     * @throws Exception
     */
    public Boolean bShopkeeper(Long fid, Long uid) throws Exception {
        if (fid == null || fid == 0)
            return false;
        if (uid == null || uid == 0)
            return false;
        int result = staffMapper.bShopkeeper(fid, uid);
        if (result > 0)
            return true;
        return false;
    }

    /**
     * 根据驿馆ID和伙计ID查询驿馆伙计信息。 wanglei于2018/10/25增加
     * 
     * @param egid
     * @param uid
     * @return
     * @throws Exception
     */
    public EgUser getById(Long egid, Long uid) throws Exception {
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", egid).andEqualTo("uid", uid);
        EgStaffEntity entity = staffMapper.selectOneByExample(example);
        return entity != null ? entity.createUser() : null;
    }

    /**
     * 添加驿馆伙计。 wanglei于2019/1/3增加
     * 
     * @param egid
     * @param uid
     * @return
     * @throws Exception
     */
    @Transactional(transactionManager = "eguanTransactionManager", rollbackFor = Exception.class)
    public EgUser create(Long egid, Long uid) throws Exception {
        // 添加驿馆伙计时，默认的角色为伙计，权限为任务管理权限
        EgRole defaultRole = configInfo.role(EgRole.STAFF).get(EgScope.TAVERN);
        EgStaffEntity entity = new EgStaffEntity(egid, uid, defaultRole.getRid(), defaultRole.getPurview());
        int insertCount = staffMapper.insertSelective(entity);
        return insertCount > 0 ? entity.createUser() : null;
    }

    /**
     * 根据egid和uid更新驿馆伙计角色和权限
     * 
     * @param egid
     * @param uid
     * @param role
     * @return
     * @throws Exception
     */
    private int updterole(Long egid, Long uid, EgRole role) throws Exception {
        // 1、构造更新条件
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", egid).andEqualTo("uid", uid);
        EgStaffEntity entity = new EgStaffEntity(egid, uid, role.getRid(), role.getPurview());
        // 2、根据更新条件更新用户信息
        int result = staffMapper.updateByExampleSelective(entity, example);
        return result;
    }

    /**
     * 根据egid和uid查询驿馆伙计的角色和权限
     * 
     * @param egid
     * @param uid
     * @return
     * @throws Exception
     */
    private EgStaffEntity detail(Long egid, Long uid) throws Exception {
        Example example = new Example(EgStaffEntity.class);
        example.and().andEqualTo("egid", egid).andEqualTo("uid", uid);
        EgStaffEntity entity = staffMapper.selectOneByExample(example);
        return entity;
    }

    /**
     * 转换为员工实体
     * 
     * @param egid
     * @param uids
     * @return
     * @throws Exception
     */
    private List<EgStaffEntity> staffConvert(Long egid, List<Long> uids) throws Exception {
        List<EgStaffEntity> staffEntities = null;
        if (uids != null && uids.size() > 0) {
            staffEntities = new ArrayList<>();
            // 1、获取系统内置员工角色Id和对应权限
            EgRole role = configInfo.role(EgRole.STAFF).get(EgScope.TAVERN);
            // 2、根据egid和uids转换成驿馆伙计实体列表
            staffEntities = uids.stream().map(u -> new EgStaffEntity(egid, u, role.getRid(), role.getPurview()))
                    .collect(Collectors.toList());
        }
        return staffEntities;
    }
}